package net.easyjava.third.aliyun.oss;

import com.aliyun.oss.OSSClient;
import com.aliyun.oss.model.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import javax.imageio.ImageIO;
import javax.imageio.stream.ImageOutputStream;
import javax.servlet.http.HttpServletRequest;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

/**
 * Created by wxnacy on 16/6/1.
 */
public class AliyunOSSClient extends BaseOSSClient {
    private static Logger logger = LoggerFactory.getLogger(AliyunOSSClient.class);
    /**
     * 构造单例
     */
    private volatile static AliyunOSSClient singleton;

    private AliyunOSSClient(final String accessId, final String accessKey) {
        this.accessId = accessId;
        this.accessKey = accessKey;
    }

    public static AliyunOSSClient getInstance(final String accessId, final String accessKey) {
        if (singleton == null) {
            synchronized (AliyunOSSClient.class) {
                if (singleton == null) {
                    singleton = new AliyunOSSClient(accessId, accessKey);
                }
            }
        }
        return singleton;
    }




    /**
     * 获取分片上传唯一标示uploadid
     * @param endpoint
     * @param bucket
     * @param key
     * @return
     */
    public String getMultipartUploadId(String endpoint,String bucket,String key){
        OSSClient client = getClient(endpoint);
        InitiateMultipartUploadRequest request = new InitiateMultipartUploadRequest(bucket, key);
        InitiateMultipartUploadResult result = client.initiateMultipartUpload(request);
        String uploadId = result.getUploadId();
//        client.shutdown();
        return uploadId;
    }

    /**
     * 上传分片
     * @param endpoint
     * @param bucket
     * @param uploadId
     * @param is
     * @param size
     * @param partNumber
     * @param key
     * @return
     */
    public PartETag uploadMultiPart(String endpoint,String bucket,String uploadId,InputStream is,long size,int partNumber,String key){
        OSSClient client = getClient(endpoint);
        UploadPartRequest uploadPartRequest = new UploadPartRequest();
        uploadPartRequest.setBucketName(bucket);
        uploadPartRequest.setKey(key);
        uploadPartRequest.setUploadId(uploadId);
        uploadPartRequest.setInputStream(is);
        // 设置分片大小，除最后一个分片外，其它分片要大于100KB
        uploadPartRequest.setPartSize(size);
        // 设置分片号，范围是1~10000，
        uploadPartRequest.setPartNumber(partNumber);
        UploadPartResult uploadPartResult = client.uploadPart(uploadPartRequest);
        PartETag partETag = uploadPartResult.getPartETag();

//        client.shutdown();
        return partETag;
    }


    /**
     * 获取所有分片
     * @param endpoint
     * @param bucket
     * @param uploadId
     * @param key
     * @return
     */
    public List<PartETag> getMultiParts(String endpoint,String bucket,String uploadId,String key){
        OSSClient ossClient = getClient(endpoint);
        List<PartETag> list = new ArrayList<>();
        // 列举所有已上传的分片
        PartListing partListing;
        ListPartsRequest listPartsRequest = new ListPartsRequest(bucket, key, uploadId);
        do {
            partListing = ossClient.listParts(listPartsRequest);
            for (PartSummary part : partListing.getParts()) {
                PartETag partETag = new PartETag(part.getPartNumber(),part.getETag());
                partETag.setETag(part.getETag());
                list.add(partETag);
            }
            listPartsRequest.setPartNumberMarker(partListing.getNextPartNumberMarker());
        } while (partListing.isTruncated());
        // 关闭client
//        ossClient.shutdown();
        return list;
    }

    /**
     * 完成分片上传
     * @param endpoint
     * @param bucket
     * @param uploadId
     * @param partETags
     * @param key
     * @return
     */
    public String uploadMulti(String endpoint,String bucket,String uploadId,List<PartETag> partETags,String key){
        OSSClient ossClient = getClient(endpoint);
        Collections.sort(partETags, new Comparator<PartETag>() {
            @Override
            public int compare(PartETag p1, PartETag p2) {
                return p1.getPartNumber() - p2.getPartNumber();
            }
        });
        CompleteMultipartUploadRequest completeMultipartUploadRequest =
                new CompleteMultipartUploadRequest(bucket, key, uploadId, partETags);
        ossClient.completeMultipartUpload(completeMultipartUploadRequest);
//        ossClient.shutdown();
        return key;
    }




    public String uploadByRequest(String endpoint, String bucket, HttpServletRequest request, String inputName) throws IOException {
        return this.uploadByRequest(endpoint, bucket, request, inputName, null);
    }

    /**
     * 通过request上传文件
     *
     * @param endpoint
     * @param bucket
     * @param request
     * @param inputName input域的name
     * @param root
     * @return
     * @throws IOException
     */
    public String uploadByRequest(String endpoint, String bucket, HttpServletRequest request, String inputName, String root) throws IOException {
        // 转型为MultipartHttpRequest：
        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
        // 获得文件：
        MultipartFile file = multipartRequest.getFile(inputName);
        // 获得文件名：
        String fileName = file.getOriginalFilename();
        String contentType = file.getContentType();
        InputStream is = file.getInputStream();


        boolean isImage = false;
        switch (contentType) {
            case "image/pjpeg":
            case "image/jpeg":

            case "image/png":
            case "image/gif":
            case "image/bmp":
                isImage = true;
                break;
            default:
                break;
        }
        fileName = createKey(root, fileName);
        if (isImage) {
            BufferedImage bi = ImageIO.read(file.getInputStream());
            String suffix = fileName.substring(fileName.lastIndexOf("."));
            fileName = fileName + "_" + bi.getWidth() + "x" + bi.getHeight() + suffix;
        }

        OSSClient client = new OSSClient(endpoint, accessId, accessKey);
        ObjectMetadata objectMeta = new ObjectMetadata();
        objectMeta.setContentLength(file.getSize());
        System.out.println("contentType = " + contentType);
        objectMeta.setContentType(contentType);
        client.putObject(bucket, fileName, is, objectMeta);
        // 关闭client
//        client.shutdown();
        if (is != null) {
            is.close();
        }
        return fileName;
    }


    @Deprecated
    public String uploadByFile(String endpoint, String bucket, String root, String path) throws IOException {
        return this.upload(endpoint, bucket, this.accessId, this.accessKey, root, TYPE_LOCAL, path, null, null);
    }
    @Deprecated
    public String uploadByFile(String endpoint, String bucket, String path) throws IOException {
        return this.uploadByFile(endpoint, bucket, null, path);
    }
    @Deprecated
    public String uploadByUrl(String endpoint, String bucket, String root, String url) throws IOException {
        return this.upload(endpoint, bucket, this.accessId, this.accessKey, root, TYPE_WEB, null, url, null);
    }
    @Deprecated
    public String uploadByUrl(String endpoint, String bucket, String url) throws IOException {
        return this.uploadByUrl(endpoint, bucket, null, url);
    }

    public String upload(String endpoint, String bucket, File file) throws IOException {
        return super.upload(endpoint, bucket, file, null);
    }
    @Override
    public String upload(String endpoint, String bucket, File file, String key) throws IOException {
        return super.upload(endpoint, bucket, file, key);
    }

    public String upload(String endpoint, String bucket, URL url) throws IOException {
        return super.upload(endpoint, bucket, url, null);
    }
    @Override
    public String upload(String endpoint, String bucket, URL url, String key) throws IOException {
        return super.upload(endpoint, bucket, url, key);
    }
    @Override
    public String upload(String endpoint, String bucket, InputStream inputStream,String key) throws IOException {
        return super.upload(endpoint, bucket, inputStream, key);
    }

    public String upload(String endpoint, String bucket, BufferedImage bi ,String siffix,String key) throws IOException {
        ByteArrayOutputStream bs = new ByteArrayOutputStream();
        ImageOutputStream imOut = ImageIO.createImageOutputStream(bs);
        ImageIO.write(bi, siffix,imOut);
        //System.out.println(bs.toByteArray().length);
        InputStream input = new ByteArrayInputStream(bs.toByteArray());
        imOut.close();
        bs.close();

        return this.upload(endpoint, bucket, input, key);
    }


    public static void main(String[] args) {
        String url = "http://banzou.wo99.net:2012/banzou_1234//7/4/temp/wo99.com_1203752648460063.mp3";
        try {
            URL u = new URL(url);
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }


    }


}
